package indi.cloud.common.utils;

import com.alibaba.fastjson.JSONArray;
import com.google.common.primitives.Doubles;

import java.math.BigDecimal;
import java.math.BigInteger;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;
import java.util.Map;

import static java.lang.Double.NaN;

/**
 * @author yangyifan
 * @version 1.0
 * @date 2021/9/28 18:15
 * @Description
 */
public class CommonDataUtils {

    private static Map<String, String> buildLevel2IndicatorNameMapper;


    /**
     * 中位数(int)
     *
     * @param nums: A list of integers.
     * @return: An integer denotes the middle number of the array.
     */
    public static Double median(Double[] nums) {
        if (nums.length == 0) {
            return null;
        }
        int start = 0;
        int end = nums.length - 1;
        int index = partition(nums, start, end);
        if (nums.length % 2 == 0) {
            while (index != nums.length / 2 - 1) {
                if (index > nums.length / 2 - 1) {
                    index = partition(nums, start, index - 1);
                } else {
                    index = partition(nums, index + 1, end);
                }
            }
        } else {
            while (index != nums.length / 2) {
                if (index > nums.length / 2) {
                    index = partition(nums, start, index - 1);
                } else {
                    index = partition(nums, index + 1, end);
                }
            }
        }
        return nums[index];
    }

    private static int partition(Double nums[], int start, int end) {
        int left = start;
        int right = end;
        Double pivot = nums[left];
        while (left < right) {
            while (left < right && nums[right] >= pivot) {
                right--;
            }
            if (left < right) {
                nums[left] = nums[right];
                left++;
            }
            while (left < right && nums[left] <= pivot) {
                left++;
            }
            if (left < right) {
                nums[right] = nums[left];
                right--;
            }
        }
        nums[left] = pivot;
        return left;
    }


    /**
     * json数组追加企业名称key
     *
     * @param name
     * @param jsonArray
     * @return
     */
    public static JSONArray appendEntName(String name, JSONArray jsonArray) {
        if (null == jsonArray) {
            return new JSONArray();
        }
        for (int i = 0; i < jsonArray.size(); i++) {
            jsonArray.getJSONObject(i).put("enterpriseName", name);
        }
        return jsonArray;
    }

    public static String colorConvert(Integer industryRatingLevel) {
        return industryRatingLevel == null ? "-" : industryRatingLevel == 1 ? "绿 " :
                industryRatingLevel == 2 ? "黄 " :
                        industryRatingLevel == 3 ? "橙 " :
                                industryRatingLevel == 4 ? "红 " : "无 ";
    }


    public static BigDecimal strToDeci(Object value, int fl) {
        return strToDeciImpl(value, fl);
    }

    public static BigDecimal strToDeci(Object value) {
        return strToDeciImpl(value, 4);
    }


    /**
     * String 转BigDecimal
     *
     * @return
     */
    public static BigDecimal strToDeciImpl(Object value, int fl) {
        BigDecimal ret = null;
        try {
            if (value != null) {
                if ("NaN".equalsIgnoreCase(String.valueOf(value))) {
                    return null;
                }
                if (value instanceof BigDecimal) {
                    ret = (BigDecimal) value;
                } else if (value instanceof String) {
                    value = ((String) value).replaceAll(",", "").trim();
                    if (((String) value).indexOf("E") > 0) {
                        BigDecimal bd = new BigDecimal(String.valueOf(value));
                        value = bd.toPlainString();
                    }
                    ret = new BigDecimal((String) value);
                } else if (value instanceof BigInteger) {
                    ret = new BigDecimal((BigInteger) value);
                } else if (value instanceof Number) {
                    if (String.valueOf(value).indexOf("E") > 0) {
                        BigDecimal bd = new BigDecimal(String.valueOf(value));
                        value = bd.toPlainString();
                        ret = new BigDecimal((String) value);
                    } else {
                        if (value instanceof Double) {
                            if (Double.isNaN(Double.valueOf(String.valueOf(value))) || Double.isInfinite(Double.valueOf(String.valueOf(value)))) {
                                ret = new BigDecimal(0);
                            } else {
                                ret = new BigDecimal(((Number) value).doubleValue());
                            }
                        }
                        if (value instanceof Integer) {
                            ret = new BigDecimal(value.toString());
                        }
                    }
                } else {
                    throw new ClassCastException("Not possible to coerce [" + value + "] from class " + value.getClass() + " into a BigDecimal.");
                }
            } else {
                throw new ClassCastException("获取科目数值为 [" + value + "]");
            }
        } catch (Exception e) {
            throw new ClassCastException("数字转BigDeciaml失败 [" + value + "]");
        }
        ret = ret.setScale(fl, BigDecimal.ROUND_HALF_DOWN);
        return ret;
    }

    /**
     * 计算目标数据在数据集中所处分位
     *
     * @param data
     * @param target
     * @return
     */
    public static Double getPosition(List<Double> data, double target) {
        double[] doubles = Doubles.toArray(data);
        // 需要对数据进行排序
        Arrays.sort(doubles);
        double result;
        // 小于目标值的数量
        int lt = 0;
        // 如果是第二种情况，则用lt2来记录比a小的数据量，它等于比c小的数据量减去a出现的次数。
        int lt2 = 1;
        int pos = -1;
        double a = NaN;
        double c = NaN;
        for (int i = 0; i < doubles.length; i++) {
            if (doubles[i] == target) {
                pos = i;
                break;
            } else if (doubles[i] < target) {
                lt++;
                if (doubles[i] == a) {
                    lt2++;
                } else {
                    lt2 = 1;
                    a = doubles[i];
                }
            } else {
                c = doubles[i];
                break;
            }
        }
        if (data.size() == 1 && pos == 0) {
            return 100.00;
        }
        // 若目标b不在数组中，则需要找到目标值临近的两个数（例如ac之于b）的位置，通过Pb = Pa + ((b-a)/(c-a))*(Pc-Pa)
        Pc:
        result = (double) lt / (doubles.length - 1);
        if (pos < 0) {
            double Pa = (double) (lt - lt2) / (doubles.length - 1);
            result = Pa + ((target - a) / (c - a)) * (result - Pa);
        }
        return result * 100;
    }


    public static void main(String[] args) {
        List dsa = Arrays.asList(1, 3, 5, 6);
        System.out.println(getPosition(dsa, 1));
        System.out.println(getPosition(dsa, 2));
        System.out.println(getPosition(dsa, 3));
        System.out.println(getPosition(dsa, 4));
        System.out.println(getPosition(dsa, 6));
        System.out.println(getPosition(dsa, 7));
    }


}
